package Hard;

import java.util.Arrays;
import java.util.Stack;

//32.最长有效括号
//难点：()(()的结果是2，不是4 同时要满足(()的结果是2，而不是0
//难点：同时满足()(()的结果是2，()(())的结果是6，而不能是4
public class Solution32 {
    public static int longestValidParentheses_err(String s) {
        int sum = 0;
        int maxSum = 0;
        Stack stack = new Stack();
        char pre = '@';
        for (int i = 0; i < s.length();i++ ) {
            if (s.charAt(i) == '(') {
                stack.push('(');
            } else if (s.charAt(i) == ')') {
                try{
                    pre= (char) stack.pop();
                    sum+=2;
                    boolean boo=false;//boo用于判断当前位置之后是不是都只有左括号
                    int k;
                    for(k=i+1;k<s.length();k++){
                        if(s.charAt(k)!='(') break;
                    }
                    if(k==s.length()){
                        boo=true;
                    }
                    if((i+1==s.length()||boo)&&!stack.empty()){
                        //透支减二法，无法适用于特殊情况：从第一个右括号开始（该右括号前面必须有若干左括号），后面全部都是一个左括号一个右括号的情况
                        //()(()、()((())、()((()())
                        //(()()
                        sum-=2;
                        //判断是否为特殊情况
                        //首先找到第一个右括号
                        int j;
                        Stack specialStack = new Stack();
                        for(j = 0 ; j < s.length() && s.charAt(j)!=')' ; j++){
                            specialStack.push(s.charAt(j));
                        }
                        //判断这个右括号前面有没有左括号
                        if(specialStack.empty()){
                            //如果没有左括号，则找到第一个左括号
                            for(;j<s.length()&&s.charAt(j)!='(';j++){}
                            //然后找到第一个右括号
                            for(;j<s.length()&&s.charAt(j)!=')';j++){}
                        }
                        //判断是不是一个左一个右的循环
                        boolean yes = true;
                        j++;
                        while (j<s.length()){
                            if(!s.substring(j,j+2).equals("()")){
                                yes=false;
                                break;
                            }
                            j+=2;
                        }
                        if(yes)
                            sum+=2;
                    }
                }catch (Exception e){
                    //())的情况和()))的情况：当前子串sum应该=2
                    //)))的情况：当前子串sum应该=0
                    if(pre=='('){
                        sum=0;
                    }else if(pre=='@'){
                        sum=0;
                    }
                    pre='@';
                }
            }
            if (sum > maxSum)
                maxSum = sum;
        }
        return maxSum;
    }
    //动态规划法
    public static int longestValidParentheses_right1(String s){
        //两两检查，如果是()的形式，的dp[i]=dp[i-2]+2
        //        如果是()的形式，则寻找当前最长子串前面有没有可以匹配的左括号
        int[] dp = new int[s.length()];//初值都为0
        int max = 0;
        for(int i = 1 ; i < s.length() ; i++){
            if(s.charAt(i-1)=='('&&s.charAt(i)==')'){
                if(i==1)
                    dp[i]=2;
                else
                    dp[i]=dp[i-2]+2;
            }
            if(s.charAt(i-1)==')'&&s.charAt(i)==')'){
                //看看i-1为截止点的最长子串的前面一个位置是不是(，如果是的话，说明可以找到一个正确的(来匹配当前的)
                if(i-1-dp[i-1]<0){
                    //())的情况
                    dp[i]=0;
                }else if(s.charAt(i-1-dp[i-1])=='(')
                    //(  )  (  (  )  )
                    //0  2  0  0  2  6
                    dp[i]=dp[i-1]+dp[i-1-dp[i-1]-1 < 0 ? 0 : i-1-dp[i-1]-1]+2;
            }
            if(dp[i]>max)
                max=dp[i];
        }
        return max;
    }
    public static void main(String[] args) {
        //")(((((()())()()))()(()))("
        System.out.println(longestValidParentheses_right1("())"));
    }
}
